<?php
declare(strict_types=1);

namespace app\controller\api;

use think\Request;
use think\exception\ValidateException;
use app\controller\api\ApiBaseController;
use think\facade\Filesystem;
use app\model\api\admin\general\Attachment;

class UploadController extends ApiBaseController
{
    protected $config = [
        // 文件路径
        'save_path' => '/uploads/{scene}/img/{year}/{mon}/{day}',
        // 最大可上传大小 KB
        'max_size' => 2048000,
        // 可上传文件后缀
        'ext' => 'jpg,jpeg,png,bmp,gif',
        //mimetype
        'mimetype' => 'image/jpeg,image/png,image/bmp,image/gif',
    ];

    public function upload(Request $request)
    {
        $params = $request->only([
            'scene' => 'default',
            'up_type' => 'img',
        ]);
        return $this->_upload($request, $params['scene'], $params['up_type']);
    }

    // 对外开放的 上传
    public function uploadOut(Request $request)
    {
        $params = $request->only([
            'scene' => 'out',
            'up_type' => 'out_file',
        ]);
        return $this->_upload($request, $params['scene'], $params['up_type']);
    }

    private function _upload($request, $up_scene = 'default', $up_type = 'img')
    {
        $file = $request->file('file');
        if (empty($file)) {
            return $this->error('请选择上传文件');
        }

        $this->iniConfig($up_type);
        try {
            $files['file'] = $file;
            validate([
                'file' => [
                    'fileSize' => $this->config['max_size'] * 1024,
                    'fileExt' => $this->config['ext'],
                    // 'fileMime' => $this->config['mimetype'],
                ],
            ])->check($files);

            $cfg_filesystem = config('filesystem');
            $disk = env('upload_disk', 'pulic');

            $save_name = Filesystem::disk($disk)->putFile($this->getSavePath($up_scene), $file, function ($file) {
                return date('His') . uniqid();
            });
            if (!$save_name) {
                return $this->error('上传失败:请检查对应disk是否可用');
            }
            $save_name = str_replace('\\', '/', $save_name);

            $path_url = ($cfg_filesystem['disks'][$disk]['url'] ?? '') . '/' . $save_name;
            //region db
            $db_data = [
                'admin_id' => is_admin_login() ?: 0,
                'member_id' => is_login() ?: 0,
                'disk' => $disk,
                'scene' => $up_scene,
                'path' => $path_url,
                'file_mime' => $file->getMime(),
                'file_name' => substr($save_name, strrpos($save_name, '/') + 1),
                'file_ori_name' => $file->getOriginalName(), //原始名称
                'file_size' => $file->getSize(),
                'file_md5' => $file->md5(),
                'file_sha1' => '',
                // 'from_type'=>'',
            ];
            $attachment = Attachment::create($db_data);
            //endregion

            if ($attachment->id) {
                return $this->success('上传成功', [
                    'src' => $path_url,
                    'attachment' => $attachment->hidden(['delete_time']),
                ]);
            } else {
                return $this->error('上传失败 DB错误');
            }
        } catch (ValidateException $e) {
            $error = $e->getMessage();
            // 过滤服务器目录信息
            $t_root = root_path();
            strpos($error, $t_root) !== false && $error = strstr($error, $t_root, true);
            return $this->error($error);
        }
    }

    private function iniConfig($up_type)
    {
        $cfg_upload = config('upload');
        $default_type = $cfg_upload['default'];
        if ($up_type != '' && in_array($up_type, array_keys($cfg_upload['up_type']))) {
            $default_type = $up_type;
        }
        $this->config = array_merge($this->config, $cfg_upload['up_type'][$default_type]);
    }
    private function getSavePath($scene = 'default')
    {
        $replace_c = [
            '{scene}' => $scene,
            '{year}' => date("Y"),
            '{mon}' => date("m"),
            '{day}' => date("d"),
            '{hour}' => date("H"),
            '{min}' => date("i"),
            '{sec}' => date("s"),
            // '{random}'   => Random::alnum(16),
            // '{random32}' => Random::alnum(32),
        ];

        $save_path = $this->config['save_path'];
        $save_path = str_replace(array_keys($replace_c), array_values($replace_c), $save_path);
        return $save_path;
    }
}
